﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using MovieBrowser.Controller;
using MovieBrowser.Event;
using MovieBrowser.Model;
using MovieBrowser.Presentation.Events;
using MovieBrowser.Util;
using NavigateEventArgs = MovieBrowser.Event.NavigateEventArgs;
using NymphsLib.CommonUtilities;

namespace MovieBrowser.Presentation.Viewer
{
    public partial class MovieInfoStatusAlt : UserControl, IDebugLogEvent, IWebNavigateEvent, ISearchMovieEvent, IMoviePersonalNoteChangeEvent
    {
        public Movie SelectedMovie { get; set; }

        public MovieBrowserController Controller { get; set; }

        public event EventHandler DebugText;
        public void InvokeOnDebugText(Exception exception)
        {
            var handler = DebugText;
            if (handler != null) handler(this, new DebugTextEventArgs(exception));
        }
        public void InvokeOnDebugText(string text)
        {
            var handler = DebugText;
            if (handler != null) handler(this, new DebugTextEventArgs(text));
        }
        //
        public event EventHandler MovieSearch;
        public void InvokeOnMovieSearchCriteriaClick(CriteriaSearchEventArgs e)
        {
            EventHandler handler = MovieSearch;
            if (handler != null) handler(this, e);
        }
        //
        public event EventHandler NavigateWeb;
        public void InvokeOnNavigateWeb(NavigateEventArgs e)
        {
            EventHandler handler = NavigateWeb;
            if (handler != null) handler(this, e);
        }
        //
        public event EventHandler NoteChange;
        public void InvokeNoteChange(Note note, object value)
        {
            EventHandler handler = NoteChange;
            if (handler != null) handler(this, new PersonalNoteUpdateEventArgs(note, value));
        }

        //
        public MovieInfoStatusAlt()
        {
            InitializeComponent();
        }

        public void LoadMovie(Movie rowMovie)
        {
            if (rowMovie == null) return;
            SelectedMovie = rowMovie;

            var movie = Controller.Db.Movies.FirstOrDefault(a => a.ImdbId == rowMovie.ImdbId);
            if (movie == null)
            {

                if (rowMovie.IsValidMovie)
                {
                    lblTitle.Text = rowMovie.Title;
                    lblRating.Text = rowMovie.Rating + "";
                    lblYear.Text = rowMovie.Year + "";
                }
                else
                {
                    lblTitle.Text = "";
                    lblRating.Text = "";
                    lblYear.Text = "";
                }
                lblRuntime.Text = "";
                lblMPAA.Text = "";
                textHighlight.Text = "";

                LoadGenres(null);
                LoadPeople(-1, null, flowDirectors);
                LoadPeople(-1, null, flowStars);
                LoadFileSystem(null);
            }
            else
            {
                lblTitle.Text = movie.Title;
                lblRating.Text = movie.Rating.ToString();
                lblYear.Text = movie.Year.ToString();

                lblRuntime.Text = movie.Runtime;
                lblMPAA.Text = movie.MPAA;
                textHighlight.Text = movie.Highlight;

                LoadGenres(Controller.Db.MovieGenres.Where(a => a.Movie.Id == movie.Id).Select(o => o.Genre).ToList());
                LoadPeople(movie.Id, Controller.Db.Directors.Where(a => a.Movie.Id == movie.Id).Select(o => o.Person).ToList(), flowDirectors);
                LoadPeople(movie.Id, Controller.Db.Stars.Where(a => a.Movie.Id == movie.Id).Select(o => o.Person).ToList(), flowStars);
                LoadFileSystem(Controller.Db.MovieFilesystems.Where(a => a.Movie.Id == movie.Id).ToList());

                MovieKeyValue mkv = Controller.Db.MovieKeyValues.FirstOrDefault(a => a.Movie.Id == movie.Id && a.Key == "Subtitle");
                tbSubtitle.Checked = mkv != null && Convert.ToBoolean(mkv.Value);
            }
            if (Authorization.IsAuthorized)
            {
                var personalNote = Controller.Db.MoviePersonalNotes.FirstOrDefault(o => o.User.Id == Authorization.LoggedInUser.Id && o.Movie.ImdbId == rowMovie.ImdbId);
                LoadPersonalNote(personalNote);
            }
            else
            {
                LoadPersonalNote(null);
            }
        }
        void LoadPersonalNote(MoviePersonalNote note)
        {
            if (note == null)
            {
                rsUserRating.Rating = 0;

                tbDislikeIt.Checked = false;
                tbLikeIt.Checked = false;
                tbHaveIt.Checked = false;
                tbSeenIt.Checked = false;
                tbWantToWatch.Checked = false;

                tbDislikeIt.Image = Properties.Resources.hate_it_dis;
                tbLikeIt.Image = Properties.Resources.like_it_dis;
                tbHaveIt.Image = Properties.Resources.have_it_dis;
                tbSeenIt.Image = Properties.Resources.seen_it_dis;
                tbWantToWatch.Image = Properties.Resources.watch_list_dis;
            }
            else
            {
                rsUserRating.Rating = note.Rating / 2.0;

                tbDislikeIt.Checked = note.Favourite < 0;
                tbLikeIt.Checked = note.Favourite > 0;
                tbHaveIt.Checked = note.Have;
                tbSeenIt.Checked = note.Seen;
                tbWantToWatch.Checked = note.Wishlist;

                tbDislikeIt.Image = note.Favourite < 0 ? Properties.Resources.hate_it : Properties.Resources.hate_it_dis;
                tbLikeIt.Image = note.Favourite > 0 ? Properties.Resources.like_it : Properties.Resources.like_it_dis;
                tbHaveIt.Image = note.Have ? Properties.Resources.have_it : Properties.Resources.have_it_dis;
                tbSeenIt.Image = note.Seen ? Properties.Resources.seen_it : Properties.Resources.seen_it_dis;
                tbWantToWatch.Image = note.Wishlist ? Properties.Resources.watch_list : Properties.Resources.watch_list_dis;
            }
        }

        private void LoadGenres(IEnumerable<Genre> list)
        {
            flowGenres.Controls.Clear();
            if (list == null) return;
            foreach (var item in list)
            {
                var linkLabel = new LinkLabel { Text = item.Name, AutoSize = true, Tag = item.Id, Margin = new Padding(1) };
                linkLabel.Click += (sender, obj) =>
                {
                    try
                    {
                        var me = (MouseEventArgs)obj;
                        long id = Convert.ToInt64(linkLabel.Tag);

                        if (me.Button == MouseButtons.Middle || (me.Button == MouseButtons.Left && ModifierKeys == Keys.Control))
                        {
                            InvokeOnNavigateWeb(new NavigateEventArgs("http://www.imdb.com/genre/" + Controller.Db.Genres.Where(o => o.Id == id).Select(o => o.Code).FirstOrDefault()));
                        }
                        else if (me.Button == MouseButtons.Left)
                        {
                            InvokeOnMovieSearchCriteriaClick(new CriteriaSearchEventArgs(typeof(MovieGenre), Controller.Db.MovieGenres.Where(o => o.Genre.Id == id).Select(o => o.Movie).ToList()));
                        }
                    }
                    catch (Exception exp)
                    {
                        InvokeOnDebugText(exp);
                    }
                };

                flowGenres.Controls.Add(linkLabel);
            }
        }

        private void LoadFileSystem(IEnumerable<MovieFilesystem> list)
        {
            flowFileSystem.Controls.Clear();
            if (list == null) return;
            foreach (var item in list)
            {
                var linkLabel = new LinkLabel { Text = item.ComputerName, AutoSize = true, Tag = item, Margin = new Padding(1) };
                linkLabel.Click += (sender, obj) =>
                {

                    try
                    {
                        var path = (MovieFilesystem)(linkLabel.Tag);
                        MovieBrowserController.ExplorerOpen(path.FolderPath);
                    }
                    catch (Exception exp)
                    {
                        InvokeOnDebugText(exp);
                    }
                };
                var toolTip = new ToolTip();
                toolTip.SetToolTip(linkLabel, item.FolderPath);
                linkLabel.ContextMenuStrip = contextMenuStrip1;
                flowFileSystem.Controls.Add(linkLabel);
            }
        }

        private void LoadPeople(long movieId, IEnumerable<Person> list, FlowLayoutPanel flowLayoutPanel)
        {
            flowLayoutPanel.Controls.Clear();
            if (list == null) return;
            foreach (var item in list)
            {
                var age = item.Age;
                age = age == "" ? age : " (" + age + ")";
                var linkLabel = new LinkLabel
                {
                    Text = item.Name + age,
                    AutoSize = true,
                    Tag = new MovieCompositeKey(movieId, item.Id),
                    ContextMenuStrip = contextMenuStrip2,
                    Margin = new Padding(1)
                };
                linkLabel.Click += (sender, obj) =>
                {
                    try
                    {
                        var me = (MouseEventArgs)obj;
                        var id = Convert.ToInt64(((MovieCompositeKey)linkLabel.Tag).SecondaryId);
                        if (me.Button == MouseButtons.Middle || (ModifierKeys == Keys.Control && me.Button == MouseButtons.Left))
                        {
                            InvokeOnNavigateWeb(new NavigateEventArgs("http://www.imdb.com/name/" + Controller.Db.People.Where(o => o.Id == id).Select(o => o.ImdbId).FirstOrDefault()));
                        }
                        else if (me.Button == MouseButtons.Left)
                        {
                            if (flowLayoutPanel == flowStars)
                            {
                                InvokeOnMovieSearchCriteriaClick(new CriteriaSearchEventArgs(typeof(Star), Controller.Db.Actors.Where(o => o.Person.Id == id).Select(o => o.Movie).ToList()));
                            }
                            else if (flowLayoutPanel == flowDirectors)
                            {
                                InvokeOnMovieSearchCriteriaClick(new CriteriaSearchEventArgs(typeof(Director), Controller.Db.Directors.Where(o => o.Person.Id == id).Select(o => o.Movie).ToList()));
                            }
                        }

                    }
                    catch (Exception exp)
                    {
                        InvokeOnDebugText(exp);
                    }
                };

                flowLayoutPanel.Controls.Add(linkLabel);
            }
        }

        private void DeleteToolStripMenuItemClick(object sender, EventArgs e)
        {
            try
            {
                var menu = (ToolStripDropDownItem)sender;
                var strip = (ContextMenuStrip)menu.Owner;
                var owner = strip.SourceControl;

                if (owner != null)
                {
                    var id = ((MovieFilesystem)owner.Tag).Id;
                    var mfs = Controller.Db.MovieFilesystems.FirstOrDefault(o => o.Id == id);
                    if (mfs == null)
                        return;
                    Controller.Db.DeleteObject(mfs);
                    Controller.Db.SaveChanges();
                }
            }
            catch (Exception exception)
            {
                InvokeOnDebugText(exception);
            }
        }

        private void LblYearLinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            try
            {
                var year = Convert.ToInt32(lblYear.Text);
                InvokeOnMovieSearchCriteriaClick(new CriteriaSearchEventArgs(typeof(Movie), Controller.Db.Movies.Where(o => o.Year == year).ToList()));
            }
            catch (Exception exp)
            {
                InvokeOnDebugText(exp);
            }
        }



        private void LblYearClick(object sender, EventArgs e)
        {
            var me = (MouseEventArgs)e;
            if (me.Button == MouseButtons.Middle || (ModifierKeys == Keys.Control && me.Button == MouseButtons.Left))
            {
                InvokeOnNavigateWeb(new NavigateEventArgs("http://www.imdb.com/year/" + lblYear.Text));
            }
        }


        private void TbWantToWatchClick(object sender, EventArgs e)
        {
            if (Authorization.IsAuthorized)
            {
                tbWantToWatch.Checked = !tbWantToWatch.Checked;
                InvokeNoteChange(Note.Wishlist, tbWantToWatch.Checked);
                //Controller.ToggleOrUpdateWishlist(Authorization.LoggedInUser, _movie, tbWantToWatch.Checked);         
                tbWantToWatch.Image = tbWantToWatch.Checked ? Properties.Resources.watch_list : Properties.Resources.watch_list_dis;
            }
        }

        private void TbLikeItClick(object sender, EventArgs e)
        {
            if (Authorization.IsAuthorized)
            {
                tbLikeIt.Checked = !tbLikeIt.Checked;
                InvokeNoteChange(Note.Like, tbLikeIt.Checked ? 1 : 0);
                //Controller.SetFavourite(Authorization.LoggedInUser, _movie, tbLikeIt.Checked);
                tbLikeIt.Image = tbLikeIt.Checked ? Properties.Resources.like_it : Properties.Resources.like_it_dis;
            }
        }

        private void TbDislikeItClick(object sender, EventArgs e)
        {
            if (Authorization.IsAuthorized)
            {
                tbDislikeIt.Checked = !tbDislikeIt.Checked;
                InvokeNoteChange(Note.Dislike, tbDislikeIt.Checked ? -1 : 0);
                // Controller.SetFavourite(Authorization.LoggedInUser, _movie, tbDislikeIt.Checked);
                tbDislikeIt.Image = tbDislikeIt.Checked ? Properties.Resources.hate_it : Properties.Resources.hate_it_dis;
            }
        }

        private void TbSeenItClick(object sender, EventArgs e)
        {
            if (Authorization.IsAuthorized)
            {
                tbSeenIt.Checked = !tbSeenIt.Checked;
                InvokeNoteChange(Note.Seen, tbSeenIt.Checked);
                //Controller.ToggleSeenIt(Authorization.LoggedInUser, _movie, tbSeenIt.Checked);
                tbSeenIt.Image = tbSeenIt.Checked ? Properties.Resources.seen_it : Properties.Resources.seen_it_dis;
            }
        }

        private void TbHaveItClick(object sender, EventArgs e)
        {
            if (Authorization.IsAuthorized)
            {
                tbHaveIt.Checked = !tbHaveIt.Checked;
                InvokeNoteChange(Note.Have, tbHaveIt.Checked);
                //Controller.ToggleHaveIt(Authorization.LoggedInUser, _movie, tbHaveIt.Checked);
                tbHaveIt.Image = tbHaveIt.Checked ? Properties.Resources.have_it : Properties.Resources.have_it_dis;
            }
        }

        private void updateToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                var menu = (ToolStripDropDownItem)sender;
                var strip = (ContextMenuStrip)menu.Owner;
                var owner = (LinkLabel)strip.SourceControl;
                var key = (MovieCompositeKey)owner.Tag;

                var people = new List<Person>();
                if (owner.Parent == flowDirectors)
                {
                    people = Controller.Db.Directors.Where(a => a.Movie.Id == key.MovieId && a.Person.Id == key.SecondaryId).Select(a => a.Person).ToList();
                }
                else if (owner.Parent == flowStars)
                {
                    people = Controller.Db.Stars.Where(a => a.Movie.Id == key.MovieId && a.Person.Id == key.SecondaryId).Select(a => a.Person).ToList();
                }
                Controller.UpdatePersonInformation(people, Controller);
            }
            catch (Exception exp)
            {
                Logger.Exception(exp, 472);
            }
        }

        private void deleteToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            try
            {
                var menu = (ToolStripDropDownItem)sender;
                var strip = (ContextMenuStrip)menu.Owner;
                var owner = (LinkLabel)strip.SourceControl;
                var key = (MovieCompositeKey)owner.Tag;


                if (owner.Parent == flowDirectors)
                {
                    var people = Controller.Db.Directors.Where(a => a.Movie.Id == key.MovieId && a.Person.Id == key.SecondaryId).ToList();
                    foreach (var person in people)
                    {
                        Controller.Db.DeleteObject(person);
                    }
                    Controller.Db.SaveChanges();
                }
                else if (owner.Parent == flowStars)
                {
                    var people = Controller.Db.Stars.Where(a => a.Movie.Id == key.MovieId && a.Person.Id == key.SecondaryId).ToList();
                    foreach (var person in people)
                    {
                        Controller.Db.DeleteObject(person);
                    }
                    Controller.Db.SaveChanges();
                }
            }
            catch (Exception exp)
            {
                Logger.Exception(exp, 472);
            }
        }

        private void tbSubtitle_Click(object sender, EventArgs e)
        {
            tbSubtitle.Checked = !tbSubtitle.Checked;
            InvokeNoteChange(Note.Subtitle, tbSubtitle.Checked);
        }

        private void rsUserRating_RatingValueChanged(object sender, NymphsLib.RatingControl.RatingChangedEventArgs e)
        {
            if (Authorization.IsAuthorized)
            {
                InvokeNoteChange(Note.Rating, rsUserRating.Rating * 2.0);
            }
        }


    }
}
